<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>仲灏小栈</title>
    <meta name="generator" content="VuePress 1.9.5">
    <link rel="icon" href="/img/favicon.ico">
    <meta name="description" content="专注web全栈学习与总结。JavaScript,js,ES6,TypeScript,vue,python,css3,html5,Node,git,github等技术文章。">
    <meta name="keywords" content="前端博客,个人技术博客,前端,前端开发,前端框架,web前端,前端面试题,技术文档,学习,面试,JavaScript,js,ES6,TypeScript,vue,python,css3,html5,Node,git,github,markdown">
    <meta name="baidu-site-verification" content="code-5CGlqw1B4p">
    <meta name="google-site-verification" content="PbO8RiLRwDnNwqNFNGnaxZnEFB3CqcGMCGoloYfQXV0">
    <meta name="theme-color" content="#65d1a0">
    
    <link rel="preload" href="/assets/css/0.styles.6c1f7aaa.css" as="style"><link rel="preload" href="/assets/js/app.6d26e8d4.js" as="script"><link rel="preload" href="/assets/js/2.8273876b.js" as="script"><link rel="preload" href="/assets/js/126.ccdb194e.js" as="script"><link rel="prefetch" href="/assets/js/10.cb095657.js"><link rel="prefetch" href="/assets/js/100.fbcd69a7.js"><link rel="prefetch" href="/assets/js/101.8fad45f8.js"><link rel="prefetch" href="/assets/js/102.16b0b3d1.js"><link rel="prefetch" href="/assets/js/103.c2af4d4a.js"><link rel="prefetch" href="/assets/js/104.d37d4660.js"><link rel="prefetch" href="/assets/js/105.27e54103.js"><link rel="prefetch" href="/assets/js/106.e4098682.js"><link rel="prefetch" href="/assets/js/107.8efeef5d.js"><link rel="prefetch" href="/assets/js/108.6c305bbf.js"><link rel="prefetch" href="/assets/js/109.6f1c6613.js"><link rel="prefetch" href="/assets/js/11.d1f39b42.js"><link rel="prefetch" href="/assets/js/110.6f264ba6.js"><link rel="prefetch" href="/assets/js/111.1b6294ef.js"><link rel="prefetch" href="/assets/js/112.2ad16154.js"><link rel="prefetch" href="/assets/js/113.a40acefc.js"><link rel="prefetch" href="/assets/js/114.d44cb107.js"><link rel="prefetch" href="/assets/js/115.bd15b919.js"><link rel="prefetch" href="/assets/js/116.778a9058.js"><link rel="prefetch" href="/assets/js/117.19ff15b7.js"><link rel="prefetch" href="/assets/js/118.2630ca8d.js"><link rel="prefetch" href="/assets/js/119.604bd439.js"><link rel="prefetch" href="/assets/js/12.892c0d9f.js"><link rel="prefetch" href="/assets/js/120.43a964f8.js"><link rel="prefetch" href="/assets/js/121.5993f55a.js"><link rel="prefetch" href="/assets/js/122.6c054fcf.js"><link rel="prefetch" href="/assets/js/123.95ddd9a3.js"><link rel="prefetch" href="/assets/js/124.c3a9510e.js"><link rel="prefetch" href="/assets/js/125.612c461a.js"><link rel="prefetch" href="/assets/js/127.865789a0.js"><link rel="prefetch" href="/assets/js/128.9e0bc723.js"><link rel="prefetch" href="/assets/js/129.68515ee6.js"><link rel="prefetch" href="/assets/js/13.ea744146.js"><link rel="prefetch" href="/assets/js/130.32a31759.js"><link rel="prefetch" href="/assets/js/131.467e7aaf.js"><link rel="prefetch" href="/assets/js/132.3bb05df9.js"><link rel="prefetch" href="/assets/js/133.52bbf931.js"><link rel="prefetch" href="/assets/js/134.ee00e869.js"><link rel="prefetch" href="/assets/js/135.aadd30fb.js"><link rel="prefetch" href="/assets/js/136.6b5bb775.js"><link rel="prefetch" href="/assets/js/137.9d66b052.js"><link rel="prefetch" href="/assets/js/138.1df874a9.js"><link rel="prefetch" href="/assets/js/139.bd1e48e9.js"><link rel="prefetch" href="/assets/js/14.c755eadf.js"><link rel="prefetch" href="/assets/js/140.2a849d58.js"><link rel="prefetch" href="/assets/js/141.28c22cf9.js"><link rel="prefetch" href="/assets/js/142.e99735ee.js"><link rel="prefetch" href="/assets/js/143.0666fdce.js"><link rel="prefetch" href="/assets/js/144.216c1efe.js"><link rel="prefetch" href="/assets/js/145.fad2c93a.js"><link rel="prefetch" href="/assets/js/146.01533714.js"><link rel="prefetch" href="/assets/js/147.1af38e50.js"><link rel="prefetch" href="/assets/js/148.84844c3d.js"><link rel="prefetch" href="/assets/js/149.49ce06ed.js"><link rel="prefetch" href="/assets/js/15.7a29d3f4.js"><link rel="prefetch" href="/assets/js/150.234bdfef.js"><link rel="prefetch" href="/assets/js/151.89e0796a.js"><link rel="prefetch" href="/assets/js/152.389ced87.js"><link rel="prefetch" href="/assets/js/153.07285920.js"><link rel="prefetch" href="/assets/js/154.965fc5c1.js"><link rel="prefetch" href="/assets/js/155.7bf58a9a.js"><link rel="prefetch" href="/assets/js/156.99e400e4.js"><link rel="prefetch" href="/assets/js/157.b6edd5ab.js"><link rel="prefetch" href="/assets/js/158.af656e52.js"><link rel="prefetch" href="/assets/js/159.4b3d37d2.js"><link rel="prefetch" href="/assets/js/16.5c417580.js"><link rel="prefetch" href="/assets/js/160.fa1e9d1b.js"><link rel="prefetch" href="/assets/js/161.43d6f2b4.js"><link rel="prefetch" href="/assets/js/162.c0e7e60f.js"><link rel="prefetch" href="/assets/js/163.c78d27b4.js"><link rel="prefetch" href="/assets/js/164.7ee2986b.js"><link rel="prefetch" href="/assets/js/165.bbc6516b.js"><link rel="prefetch" href="/assets/js/166.90e15253.js"><link rel="prefetch" href="/assets/js/167.18578ca6.js"><link rel="prefetch" href="/assets/js/168.c52ad494.js"><link rel="prefetch" href="/assets/js/169.c34b2d53.js"><link rel="prefetch" href="/assets/js/17.76fdc3b2.js"><link rel="prefetch" href="/assets/js/170.c97f6096.js"><link rel="prefetch" href="/assets/js/171.358f0f02.js"><link rel="prefetch" href="/assets/js/172.30f03133.js"><link rel="prefetch" href="/assets/js/173.b72d5243.js"><link rel="prefetch" href="/assets/js/174.4e333643.js"><link rel="prefetch" href="/assets/js/175.2c07b836.js"><link rel="prefetch" href="/assets/js/176.29bcb24c.js"><link rel="prefetch" href="/assets/js/177.102b3f0f.js"><link rel="prefetch" href="/assets/js/178.5862bde0.js"><link rel="prefetch" href="/assets/js/179.0da54072.js"><link rel="prefetch" href="/assets/js/18.f857e697.js"><link rel="prefetch" href="/assets/js/180.393e8099.js"><link rel="prefetch" href="/assets/js/181.418f9fe8.js"><link rel="prefetch" href="/assets/js/182.e65424fa.js"><link rel="prefetch" href="/assets/js/183.3b3cb092.js"><link rel="prefetch" href="/assets/js/184.73f7a76a.js"><link rel="prefetch" href="/assets/js/185.537623fb.js"><link rel="prefetch" href="/assets/js/186.df802468.js"><link rel="prefetch" href="/assets/js/187.1095bafd.js"><link rel="prefetch" href="/assets/js/188.1d2acd1a.js"><link rel="prefetch" href="/assets/js/189.dc6a5186.js"><link rel="prefetch" href="/assets/js/19.8c1d0f81.js"><link rel="prefetch" href="/assets/js/190.a279b4dd.js"><link rel="prefetch" href="/assets/js/191.3abaa15f.js"><link rel="prefetch" href="/assets/js/192.4d0dd04e.js"><link rel="prefetch" href="/assets/js/193.2c698e6f.js"><link rel="prefetch" href="/assets/js/194.4243beaa.js"><link rel="prefetch" href="/assets/js/195.7c13b124.js"><link rel="prefetch" href="/assets/js/196.b18118bf.js"><link rel="prefetch" href="/assets/js/197.2abfac38.js"><link rel="prefetch" href="/assets/js/198.407f0a8b.js"><link rel="prefetch" href="/assets/js/199.d4e97578.js"><link rel="prefetch" href="/assets/js/20.47831bf7.js"><link rel="prefetch" href="/assets/js/200.86ce407c.js"><link rel="prefetch" href="/assets/js/201.56a65a3f.js"><link rel="prefetch" href="/assets/js/202.f852c6e8.js"><link rel="prefetch" href="/assets/js/203.92530d7a.js"><link rel="prefetch" href="/assets/js/204.ce612269.js"><link rel="prefetch" href="/assets/js/205.b14b2d70.js"><link rel="prefetch" href="/assets/js/206.b5112828.js"><link rel="prefetch" href="/assets/js/207.a4becd8a.js"><link rel="prefetch" href="/assets/js/208.f82e2766.js"><link rel="prefetch" href="/assets/js/209.11566ec8.js"><link rel="prefetch" href="/assets/js/21.8580b0b4.js"><link rel="prefetch" href="/assets/js/210.bf848e0e.js"><link rel="prefetch" href="/assets/js/211.6db52324.js"><link rel="prefetch" href="/assets/js/212.c9a03071.js"><link rel="prefetch" href="/assets/js/213.734c775f.js"><link rel="prefetch" href="/assets/js/214.7654a416.js"><link rel="prefetch" href="/assets/js/215.34ad7e3d.js"><link rel="prefetch" href="/assets/js/216.aabcd184.js"><link rel="prefetch" href="/assets/js/217.26ffe7d6.js"><link rel="prefetch" href="/assets/js/218.d8ceaf2e.js"><link rel="prefetch" href="/assets/js/219.82bad7ef.js"><link rel="prefetch" href="/assets/js/22.2d87ea68.js"><link rel="prefetch" href="/assets/js/220.0c35dcdf.js"><link rel="prefetch" href="/assets/js/221.8657d7c1.js"><link rel="prefetch" href="/assets/js/222.291af8a7.js"><link rel="prefetch" href="/assets/js/223.e8ce5ce0.js"><link rel="prefetch" href="/assets/js/224.2c3c1268.js"><link rel="prefetch" href="/assets/js/225.b31429da.js"><link rel="prefetch" href="/assets/js/226.8ec29e66.js"><link rel="prefetch" href="/assets/js/227.84469b41.js"><link rel="prefetch" href="/assets/js/228.cd6b9967.js"><link rel="prefetch" href="/assets/js/229.e5497c23.js"><link rel="prefetch" href="/assets/js/23.c1a929a6.js"><link rel="prefetch" href="/assets/js/230.643fdbb6.js"><link rel="prefetch" href="/assets/js/231.22457248.js"><link rel="prefetch" href="/assets/js/232.7e94e6f0.js"><link rel="prefetch" href="/assets/js/233.1083085e.js"><link rel="prefetch" href="/assets/js/234.6ce5972b.js"><link rel="prefetch" href="/assets/js/235.bc1d1e7e.js"><link rel="prefetch" href="/assets/js/236.f510d892.js"><link rel="prefetch" href="/assets/js/237.4690c583.js"><link rel="prefetch" href="/assets/js/238.ef69b085.js"><link rel="prefetch" href="/assets/js/239.e7cbaef4.js"><link rel="prefetch" href="/assets/js/24.707a9b9d.js"><link rel="prefetch" href="/assets/js/240.02e1ce4d.js"><link rel="prefetch" href="/assets/js/241.8ccdecd0.js"><link rel="prefetch" href="/assets/js/242.25a5eeac.js"><link rel="prefetch" href="/assets/js/243.80dc6cf3.js"><link rel="prefetch" href="/assets/js/244.d2d264c1.js"><link rel="prefetch" href="/assets/js/245.8646c059.js"><link rel="prefetch" href="/assets/js/246.0d788a8c.js"><link rel="prefetch" href="/assets/js/247.211b425b.js"><link rel="prefetch" href="/assets/js/248.15e5b430.js"><link rel="prefetch" href="/assets/js/249.b28c41d2.js"><link rel="prefetch" href="/assets/js/25.e47a8360.js"><link rel="prefetch" href="/assets/js/250.e4621bbf.js"><link rel="prefetch" href="/assets/js/251.2f49ea1d.js"><link rel="prefetch" href="/assets/js/252.c567824c.js"><link rel="prefetch" href="/assets/js/253.7eb2a6c2.js"><link rel="prefetch" href="/assets/js/254.adf8b2ad.js"><link rel="prefetch" href="/assets/js/255.43d07402.js"><link rel="prefetch" href="/assets/js/256.d49b01ff.js"><link rel="prefetch" href="/assets/js/257.cc61cd1a.js"><link rel="prefetch" href="/assets/js/258.e46ee926.js"><link rel="prefetch" href="/assets/js/259.5c84c742.js"><link rel="prefetch" href="/assets/js/26.db56ba8d.js"><link rel="prefetch" href="/assets/js/260.05cc8cff.js"><link rel="prefetch" href="/assets/js/261.1891f9c6.js"><link rel="prefetch" href="/assets/js/262.0913812a.js"><link rel="prefetch" href="/assets/js/263.a6836819.js"><link rel="prefetch" href="/assets/js/264.363da610.js"><link rel="prefetch" href="/assets/js/265.2cbfbe9f.js"><link rel="prefetch" href="/assets/js/266.555ca792.js"><link rel="prefetch" href="/assets/js/267.83f4c202.js"><link rel="prefetch" href="/assets/js/268.6dea35af.js"><link rel="prefetch" href="/assets/js/269.cbc5306b.js"><link rel="prefetch" href="/assets/js/27.0b0c1f7f.js"><link rel="prefetch" href="/assets/js/270.6bc430c5.js"><link rel="prefetch" href="/assets/js/271.f5105765.js"><link rel="prefetch" href="/assets/js/272.e1541ef7.js"><link rel="prefetch" href="/assets/js/273.158c7593.js"><link rel="prefetch" href="/assets/js/274.efb98c5b.js"><link rel="prefetch" href="/assets/js/275.cf2c3b21.js"><link rel="prefetch" href="/assets/js/276.0bf20a2d.js"><link rel="prefetch" href="/assets/js/277.2e4ddf6c.js"><link rel="prefetch" href="/assets/js/278.7f8b14ac.js"><link rel="prefetch" href="/assets/js/279.83a65d2f.js"><link rel="prefetch" href="/assets/js/28.a5d8ae18.js"><link rel="prefetch" href="/assets/js/280.47de1643.js"><link rel="prefetch" href="/assets/js/281.1d5cab51.js"><link rel="prefetch" href="/assets/js/282.b2299bce.js"><link rel="prefetch" href="/assets/js/283.fdad201b.js"><link rel="prefetch" href="/assets/js/284.cdf83f8f.js"><link rel="prefetch" href="/assets/js/285.caee6eb0.js"><link rel="prefetch" href="/assets/js/286.6b211023.js"><link rel="prefetch" href="/assets/js/287.e9e93db3.js"><link rel="prefetch" href="/assets/js/288.5892d2e1.js"><link rel="prefetch" href="/assets/js/289.48074c49.js"><link rel="prefetch" href="/assets/js/29.0bc8ea25.js"><link rel="prefetch" href="/assets/js/290.b478b2ab.js"><link rel="prefetch" href="/assets/js/291.18239d2b.js"><link rel="prefetch" href="/assets/js/292.9f6b48b4.js"><link rel="prefetch" href="/assets/js/293.70a0b924.js"><link rel="prefetch" href="/assets/js/294.bc5f021a.js"><link rel="prefetch" href="/assets/js/295.dfa72324.js"><link rel="prefetch" href="/assets/js/296.fb717477.js"><link rel="prefetch" href="/assets/js/297.2b2daf25.js"><link rel="prefetch" href="/assets/js/298.0ed3ce25.js"><link rel="prefetch" href="/assets/js/299.c59a3f82.js"><link rel="prefetch" href="/assets/js/3.d68e1d13.js"><link rel="prefetch" href="/assets/js/30.063f8dbe.js"><link rel="prefetch" href="/assets/js/300.f423c130.js"><link rel="prefetch" href="/assets/js/301.a11bcaa5.js"><link rel="prefetch" href="/assets/js/302.5a45b99e.js"><link rel="prefetch" href="/assets/js/303.80ac16da.js"><link rel="prefetch" href="/assets/js/304.f773afc2.js"><link rel="prefetch" href="/assets/js/305.52f1b3ba.js"><link rel="prefetch" href="/assets/js/306.966f2eef.js"><link rel="prefetch" href="/assets/js/307.c22143cf.js"><link rel="prefetch" href="/assets/js/308.a6dfec6e.js"><link rel="prefetch" href="/assets/js/309.377e4f0b.js"><link rel="prefetch" href="/assets/js/31.69d8f2c2.js"><link rel="prefetch" href="/assets/js/310.a76309fc.js"><link rel="prefetch" href="/assets/js/311.0706d5ca.js"><link rel="prefetch" href="/assets/js/312.40513d91.js"><link rel="prefetch" href="/assets/js/313.e36621af.js"><link rel="prefetch" href="/assets/js/314.3d4325be.js"><link rel="prefetch" href="/assets/js/315.72480163.js"><link rel="prefetch" href="/assets/js/316.83f31163.js"><link rel="prefetch" href="/assets/js/317.872fd713.js"><link rel="prefetch" href="/assets/js/318.0dc2aea4.js"><link rel="prefetch" href="/assets/js/319.454e4745.js"><link rel="prefetch" href="/assets/js/32.50aa541b.js"><link rel="prefetch" href="/assets/js/320.d9116236.js"><link rel="prefetch" href="/assets/js/321.b06a7a4e.js"><link rel="prefetch" href="/assets/js/322.41bcaaf1.js"><link rel="prefetch" href="/assets/js/323.f01ba88b.js"><link rel="prefetch" href="/assets/js/324.9a736f30.js"><link rel="prefetch" href="/assets/js/325.49b1193e.js"><link rel="prefetch" href="/assets/js/326.5a07b4a0.js"><link rel="prefetch" href="/assets/js/327.aceece56.js"><link rel="prefetch" href="/assets/js/328.e03489c3.js"><link rel="prefetch" href="/assets/js/329.5673fdef.js"><link rel="prefetch" href="/assets/js/33.4aa00ff3.js"><link rel="prefetch" href="/assets/js/330.246e74fa.js"><link rel="prefetch" href="/assets/js/331.e1cffa6b.js"><link rel="prefetch" href="/assets/js/332.2856b83e.js"><link rel="prefetch" href="/assets/js/333.d4c9c15a.js"><link rel="prefetch" href="/assets/js/334.13b03971.js"><link rel="prefetch" href="/assets/js/335.0b8ed702.js"><link rel="prefetch" href="/assets/js/336.3e71f28d.js"><link rel="prefetch" href="/assets/js/337.f929f08c.js"><link rel="prefetch" href="/assets/js/338.01a6cfbe.js"><link rel="prefetch" href="/assets/js/339.5cd647ad.js"><link rel="prefetch" href="/assets/js/34.b25c4a87.js"><link rel="prefetch" href="/assets/js/340.f941cae0.js"><link rel="prefetch" href="/assets/js/341.aa01a6b1.js"><link rel="prefetch" href="/assets/js/342.edd59a58.js"><link rel="prefetch" href="/assets/js/343.237c716b.js"><link rel="prefetch" href="/assets/js/344.06e59f2b.js"><link rel="prefetch" href="/assets/js/345.ddd4f6fe.js"><link rel="prefetch" href="/assets/js/346.70fe3c42.js"><link rel="prefetch" href="/assets/js/347.d39ad15e.js"><link rel="prefetch" href="/assets/js/348.1b135410.js"><link rel="prefetch" href="/assets/js/349.fd78d783.js"><link rel="prefetch" href="/assets/js/35.a1af8744.js"><link rel="prefetch" href="/assets/js/350.b10e7d69.js"><link rel="prefetch" href="/assets/js/351.a6ae4318.js"><link rel="prefetch" href="/assets/js/352.3117739a.js"><link rel="prefetch" href="/assets/js/353.99e022f1.js"><link rel="prefetch" href="/assets/js/354.a444c2d8.js"><link rel="prefetch" href="/assets/js/355.13d044aa.js"><link rel="prefetch" href="/assets/js/356.d2cfe5d0.js"><link rel="prefetch" href="/assets/js/357.eb44f05f.js"><link rel="prefetch" href="/assets/js/358.394c15db.js"><link rel="prefetch" href="/assets/js/359.6c541551.js"><link rel="prefetch" href="/assets/js/36.5558b717.js"><link rel="prefetch" href="/assets/js/360.65af88d5.js"><link rel="prefetch" href="/assets/js/361.d9b3c889.js"><link rel="prefetch" href="/assets/js/362.37ec0a7d.js"><link rel="prefetch" href="/assets/js/363.49690222.js"><link rel="prefetch" href="/assets/js/364.419b3dab.js"><link rel="prefetch" href="/assets/js/365.1f79df07.js"><link rel="prefetch" href="/assets/js/366.fa710c6f.js"><link rel="prefetch" href="/assets/js/367.497eeda5.js"><link rel="prefetch" href="/assets/js/368.45cf08f6.js"><link rel="prefetch" href="/assets/js/369.80a60b6a.js"><link rel="prefetch" href="/assets/js/37.511798d2.js"><link rel="prefetch" href="/assets/js/370.61b161b4.js"><link rel="prefetch" href="/assets/js/371.545f0249.js"><link rel="prefetch" href="/assets/js/372.d383f896.js"><link rel="prefetch" href="/assets/js/373.df22361b.js"><link rel="prefetch" href="/assets/js/374.0b9872ee.js"><link rel="prefetch" href="/assets/js/375.76bbca97.js"><link rel="prefetch" href="/assets/js/376.1f6f8210.js"><link rel="prefetch" href="/assets/js/377.3dd0dc75.js"><link rel="prefetch" href="/assets/js/378.32cac01d.js"><link rel="prefetch" href="/assets/js/379.6682a524.js"><link rel="prefetch" href="/assets/js/38.2dfd8d32.js"><link rel="prefetch" href="/assets/js/380.1ab9ec1d.js"><link rel="prefetch" href="/assets/js/381.cea4ec7d.js"><link rel="prefetch" href="/assets/js/382.fc51cce1.js"><link rel="prefetch" href="/assets/js/383.489718b4.js"><link rel="prefetch" href="/assets/js/384.a7a1c6d7.js"><link rel="prefetch" href="/assets/js/385.7b2d3a89.js"><link rel="prefetch" href="/assets/js/386.f0a18324.js"><link rel="prefetch" href="/assets/js/387.53063e56.js"><link rel="prefetch" href="/assets/js/388.1115759c.js"><link rel="prefetch" href="/assets/js/389.58bf8aaf.js"><link rel="prefetch" href="/assets/js/39.e8482eab.js"><link rel="prefetch" href="/assets/js/4.de17fbe4.js"><link rel="prefetch" href="/assets/js/40.c6dc3476.js"><link rel="prefetch" href="/assets/js/41.78bfe256.js"><link rel="prefetch" href="/assets/js/42.248cddd4.js"><link rel="prefetch" href="/assets/js/43.6429d3dc.js"><link rel="prefetch" href="/assets/js/44.71e9af05.js"><link rel="prefetch" href="/assets/js/45.f80fb4fc.js"><link rel="prefetch" href="/assets/js/46.3d5e7e58.js"><link rel="prefetch" href="/assets/js/47.1bbf5e9a.js"><link rel="prefetch" href="/assets/js/48.6909050b.js"><link rel="prefetch" href="/assets/js/49.9c775f82.js"><link rel="prefetch" href="/assets/js/5.59910585.js"><link rel="prefetch" href="/assets/js/50.aceb6009.js"><link rel="prefetch" href="/assets/js/51.acd0d321.js"><link rel="prefetch" href="/assets/js/52.a4f9f157.js"><link rel="prefetch" href="/assets/js/53.0f1ec943.js"><link rel="prefetch" href="/assets/js/54.6c5c2837.js"><link rel="prefetch" href="/assets/js/55.f412714f.js"><link rel="prefetch" href="/assets/js/56.64a3862c.js"><link rel="prefetch" href="/assets/js/57.d070eb7d.js"><link rel="prefetch" href="/assets/js/58.a80067c8.js"><link rel="prefetch" href="/assets/js/59.084f5e76.js"><link rel="prefetch" href="/assets/js/6.0ab71a58.js"><link rel="prefetch" href="/assets/js/60.42e0fbb5.js"><link rel="prefetch" href="/assets/js/61.b5b87c23.js"><link rel="prefetch" href="/assets/js/62.014cdbe2.js"><link rel="prefetch" href="/assets/js/63.ff1278d1.js"><link rel="prefetch" href="/assets/js/64.44a86cb2.js"><link rel="prefetch" href="/assets/js/65.1a69bd56.js"><link rel="prefetch" href="/assets/js/66.b8d9a1e9.js"><link rel="prefetch" href="/assets/js/67.48e3c0e6.js"><link rel="prefetch" href="/assets/js/68.127da596.js"><link rel="prefetch" href="/assets/js/69.77e4e1cb.js"><link rel="prefetch" href="/assets/js/7.769e6e3f.js"><link rel="prefetch" href="/assets/js/70.7863bd30.js"><link rel="prefetch" href="/assets/js/71.c5c89c65.js"><link rel="prefetch" href="/assets/js/72.030ac8a4.js"><link rel="prefetch" href="/assets/js/73.e96cf593.js"><link rel="prefetch" href="/assets/js/74.f9319fe7.js"><link rel="prefetch" href="/assets/js/75.049ce9e1.js"><link rel="prefetch" href="/assets/js/76.c71e5605.js"><link rel="prefetch" href="/assets/js/77.1e682453.js"><link rel="prefetch" href="/assets/js/78.0cce7473.js"><link rel="prefetch" href="/assets/js/79.3d32f303.js"><link rel="prefetch" href="/assets/js/8.812618a5.js"><link rel="prefetch" href="/assets/js/80.c956dc30.js"><link rel="prefetch" href="/assets/js/81.8276eaa8.js"><link rel="prefetch" href="/assets/js/82.10f6fdc6.js"><link rel="prefetch" href="/assets/js/83.cac65ec1.js"><link rel="prefetch" href="/assets/js/84.a4ce0ebf.js"><link rel="prefetch" href="/assets/js/85.d9efee67.js"><link rel="prefetch" href="/assets/js/86.cf64260c.js"><link rel="prefetch" href="/assets/js/87.e261e385.js"><link rel="prefetch" href="/assets/js/88.63b9894b.js"><link rel="prefetch" href="/assets/js/89.0ad95e30.js"><link rel="prefetch" href="/assets/js/9.c942e82a.js"><link rel="prefetch" href="/assets/js/90.77f9f729.js"><link rel="prefetch" href="/assets/js/91.3fcbf2d5.js"><link rel="prefetch" href="/assets/js/92.8b57334e.js"><link rel="prefetch" href="/assets/js/93.6095e56a.js"><link rel="prefetch" href="/assets/js/94.c616143f.js"><link rel="prefetch" href="/assets/js/95.a9b61cf9.js"><link rel="prefetch" href="/assets/js/96.a3896e7e.js"><link rel="prefetch" href="/assets/js/97.0318332c.js"><link rel="prefetch" href="/assets/js/98.17b8173b.js"><link rel="prefetch" href="/assets/js/99.d299c156.js">
    <link rel="stylesheet" href="/assets/css/0.styles.6c1f7aaa.css">
  </head>
  <body class="theme-mode-light">
    <div id="app" data-server-rendered="true"><div class="theme-container sidebar-open have-rightmenu have-body-img"><header class="navbar blur"><div title="目录" class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/img/logo.png" alt="仲灏小栈" class="logo"> <span class="site-name can-hide">仲灏小栈</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/web/" class="nav-link">大前端</a></div><div class="nav-item"><a href="/backend-opt/" class="nav-link">后端&amp;运维</a></div><div class="nav-item"><a href="/other-tech/" class="nav-link">其他技术</a></div><div class="nav-item"><a href="/tech-live/" class="nav-link">生活</a></div><div class="nav-item"><a href="/about/" class="nav-link">关于我</a></div><div class="nav-item"><a href="/favorite/" class="nav-link">收藏</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div> <a href="https://github.com/izhaong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <div class="sidebar-hover-trigger"></div> <aside class="sidebar" style="display:none;"><div class="blogger"><img src="https://cdn.jsdelivr.net/gh/izhaong/izhaong.com-oss/site-data/avatar/avatar-wx.jpg"> <div class="blogger-info"><h3>仲灏</h3> <span>诚意, 正心, 格物, 致知</span></div></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">首页</a></div><div class="nav-item"><a href="/web/" class="nav-link">大前端</a></div><div class="nav-item"><a href="/backend-opt/" class="nav-link">后端&amp;运维</a></div><div class="nav-item"><a href="/other-tech/" class="nav-link">其他技术</a></div><div class="nav-item"><a href="/tech-live/" class="nav-link">生活</a></div><div class="nav-item"><a href="/about/" class="nav-link">关于我</a></div><div class="nav-item"><a href="/favorite/" class="nav-link">收藏</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="索引" class="dropdown-title"><a href="/archives/" class="link-title">索引</a> <span class="title" style="display:none;">索引</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/" class="nav-link">分类</a></li><li class="dropdown-item"><!----> <a href="/tags/" class="nav-link">标签</a></li><li class="dropdown-item"><!----> <a href="/archives/" class="nav-link">归档</a></li></ul></div></div> <a href="https://github.com/izhaong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><a href="/note/infrastructure/" class="sidebar-link">《前端项目基础建设》</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>HTML&amp;CSS</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>JavaScript&amp;TypeScript</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Node</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>构建</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Vue</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>React</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/pages/5e7846/" class="sidebar-link">Vue 放弃繁琐的render函数，拥抱JSX</a></li><li><a href="/pages/c000dc/" class="sidebar-link">Awesome React</a></li><li><a href="/pages/bb127f/" class="sidebar-link">React 文档（vue版）</a></li><li><a href="/pages/e13969/" class="sidebar-link">react 项目开发注意事项</a></li><li><a href="/pages/477bdb/" class="sidebar-link">常见功能实现</a></li><li><a href="/pages/803923/" class="sidebar-link">react 常见坑集合</a></li><li><a href="/pages/d8f9b4/" class="sidebar-link">ant design pro 学习</a></li><li><a href="/pages/74ff3d/" class="sidebar-link">ProComponents设计思路</a></li><li><a href="/pages/1ed838/" class="sidebar-link">万条数据渲染优化</a></li><li><a href="/pages/6a4091/" class="sidebar-link">react hook 与 闭包</a></li><li><a href="/pages/bfda29/" class="sidebar-link">JSX</a></li><li><a href="/pages/c1e5fe/" class="sidebar-link">React生命周期</a></li><li><a href="/pages/b33eff/" class="sidebar-link">React 基本使用 setState</a></li><li><a href="/pages/bca771/" class="sidebar-link">React 基本使用 组件生命周期</a></li><li><a href="/pages/be9b53/" class="sidebar-link">React 高级使用 性能优化</a></li><li><a href="/pages/3101a6/" class="sidebar-link">React 高级使用 高阶组件</a></li><li><a href="/pages/56c5a3/" class="sidebar-link">React Redux使用</a></li><li><a href="/pages/62d6bf/" class="sidebar-link">react-router 使用</a></li><li><a href="/pages/6cddc4/" class="sidebar-link">React 原理</a></li><li><a href="/pages/158846/" class="sidebar-link">React 面试题1</a></li><li><a href="/pages/247d4c/" class="sidebar-link">React 面试题2</a></li><li><a href="/pages/f00d6f/" class="sidebar-link">React 面试题3</a></li><li><a href="/pages/d1bd46/" class="sidebar-link">React 面试题5</a></li><li><a href="/pages/bb30f8/" class="sidebar-link">仿jira项目笔记 项目起航：项目初始化与配置</a></li><li><a href="/pages/e398d0/" class="sidebar-link">第6章 CSS 其实很简单 - 用 CSS-in-JS 添加样式</a></li><li><a href="/pages/a9bba7/" class="sidebar-link">第8章 Hook，路由，与 URL 状态管理</a></li><li><a href="/pages/82ebb2/" class="sidebar-link">pro-components 源码学习</a></li><li><a href="/pages/88bcac/" class="sidebar-link">ant-design Spin组件封装</a></li><li><a href="/pages/7db6a2/" aria-current="page" class="active sidebar-link">React 生命周期</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>小程序</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>跨端</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>Electron</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>WebGL&amp;GIS</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>浏览器</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>面经</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>其他</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <div><main class="page"><div class="theme-vdoing-wrapper "><div class="articleInfo-wrap" data-v-06225672><div class="articleInfo" data-v-06225672><ul class="breadcrumbs" data-v-06225672><li data-v-06225672><a href="/" title="首页" class="iconfont icon-home router-link-active" data-v-06225672></a></li> <li data-v-06225672><a href="/web/#大前端" data-v-06225672>大前端</a></li><li data-v-06225672><a href="/web/#React" data-v-06225672>React</a></li></ul> <div class="info" data-v-06225672><div title="作者" class="author iconfont icon-touxiang" data-v-06225672><a href="https://github.com/izhaong" target="_blank" title="作者" class="beLink" data-v-06225672>仲灏</a></div> <div title="创建时间" class="date iconfont icon-riqi" data-v-06225672><a href="javascript:;" data-v-06225672>2023-02-08</a></div> <!----></div></div></div> <!----> <div class="content-wrapper"><div class="right-menu-wrapper"><div class="right-menu-margin"><div class="right-menu-title">目录</div> <div class="right-menu-content"></div></div></div> <h1><img src=""><!----></h1>  <div class="theme-vdoing-content content__default"><p>React 生命周期已经是一个老生常谈的话题了，几乎没有哪一门 React 入门教材会省略对组件生命周期的介绍。然而，入门教材在设计上往往追求的是“简单省事、迅速上手”，这就导致许多同学对于生命周期知识的刻板印象为“背就完了、别想太多”。</p> <p>“背就完了”这样简单粗暴的学习方式，或许可以帮助你理解“What to do”，到达“How to do”，但却不能帮助你去思考和认知“Why to do”。作为一个专业的 React 开发者，我们必须要求自己在知其然的基础上，知其所以然。</p> <p>在本课时和下一个课时，我将抱着帮你做到“知其所以然”的目的，以 React 的基本原理为引子，<strong>对 React 15、React 16 两个版本的生命周期进行探讨、比对和总结，通过搞清楚一个又一个的“Why”，来帮你建立系统而完善的生命周期知识体系</strong>。</p> <h3 id="生命周期背后的设计思想-把握-react-中的-大方向"><a href="#生命周期背后的设计思想-把握-react-中的-大方向" class="header-anchor">#</a> 生命周期背后的设计思想：把握 React 中的“大方向”</h3> <p>在介绍具体的生命周期之前，我想先带你初步理解 React 框架中的一些关键的设计思想，以便为你后续的学习提供不可或缺的“加速度”。</p> <p>如果你经常翻阅 React 官网或者 React 官方的一些文章，你会发现“<strong>组件</strong>”和“<strong>虚拟 DOM</strong>”这两个词的出镜率是非常高的，它们是 React 基本原理中极为关键的两个概念，也是我们这个小节的学习切入点。</p> <h4 id="虚拟-dom-核心算法的基石"><a href="#虚拟-dom-核心算法的基石" class="header-anchor">#</a> 虚拟 DOM：核心算法的基石</h4> <p>通过 01 课时的学习，你已经知晓了虚拟 DOM 节点的基本形态，现在我们需要简单了解下虚拟 DOM 在整个 React 工作流中的作用。</p> <p>组件在初始化时，会通过调用生命周期中的 render 方法，<strong>生成虚拟 DOM</strong>，然后再通过调用 ReactDOM.render 方法，实现虚拟 DOM 到真实 DOM 的转换。</p> <p>当组件更新时，会再次通过调用 render 方法<strong>生成新的虚拟 DOM</strong>，然后借助 diff（这是一个非常关键的算法，我将在“模块二：核心原理”重点讲解）<strong>定位出两次虚拟 DOM 的差异</strong>，从而针对发生变化的真实 DOM 作定向更新。</p> <p>以上就是 React 框架核心算法的大致流程。对于这套关键的工作流来说，“虚拟 DOM”是所有操作的大前提，是核心算法的基石。</p> <h4 id="组件化-工程化思想在框架中的落地"><a href="#组件化-工程化思想在框架中的落地" class="header-anchor">#</a> 组件化：工程化思想在框架中的落地</h4> <p>组件化是一种优秀的软件设计思想，也是 React 团队在研发效能方面所做的一个重要的努力。</p> <p>在一个 React 项目中，几乎所有的可见/不可见的内容都可以被抽离为各种各样的组件，每个组件既是“封闭”的，也是“开放”的。</p> <p>所谓“封闭”，主要是针对“渲染工作流”（指从<strong>组件数据改变</strong>到<strong>组件实际更新发生的</strong>过程）来说的。在组件自身的渲染工作流中，每个组件都只处理它内部的渲染逻辑。在没有数据流交互的情况下，组件与组件之间可以做到“各自为政”。</p> <p>而所谓“开放”，则是针对组件间通信来说的。React 允许开发者基于“单向数据流”的原则完成组件间的通信。而组件之间的通信又将改变通信双方/某一方内部的数据，进而对渲染结果构成影响。所以说在数据这个“红娘”的牵线搭桥之下，组件之间又是彼此开放的，是可以相互影响的。</p> <p>这一“开放”与“封闭”兼具的特性，使得 React 组件<strong>既专注又灵活</strong>，具备高度的可重用性和可维护性。</p> <h4 id="生命周期方法的本质-组件的-灵魂-与-躯干"><a href="#生命周期方法的本质-组件的-灵魂-与-躯干" class="header-anchor">#</a> 生命周期方法的本质：组件的“灵魂”与“躯干”</h4> <p>之前我曾经在社区读过一篇文章，文中将 render 方法形容为 React 组件的“灵魂”。当时我对这句话产生了非常强烈的共鸣，这里我就想以这个曾经打动过我的比喻为引子，帮助你从宏观上建立对 React 生命周期的感性认知。</p> <p>注意，这里提到的 render 方法，和我们 01 课时所说的 ReactDOM.render 可不是一个东西，它指的是 React 组件内部的这个生命周期方法：</p> <p>class LifeCycle extends React.Component {</p> <div class="language- line-numbers-mode"><pre class="language-text"><code>render() { console.log(&quot;render方法执行&quot;); return ( &lt;div className=&quot;container&quot;&gt; this is content &lt;/div&gt; ); } } 
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>前面咱们介绍了虚拟 DOM、组件化，倘若把这两块知识整合一下，你就会发现这两个概念似乎都在围着 render 这个生命周期打转：虚拟 DOM 自然不必多说，它的生成都要仰仗 render；而组件化概念中所提及的“渲染工作流”，这里指的是从<strong>组件数据改变</strong>到<strong>组件实际更新发生的</strong>过程，这个过程的实现同样离不开 render。</p> <p>由此看来，render 方法在整个组件生命周期中确实举足轻重，它担得起“灵魂”这个有分量的比喻。那么如果将 render 方法比作组件的“<strong>灵魂</strong>”，render 之外的生命周期方法就完全可以理解为是组件的“<strong>躯干</strong>”。</p> <p>“躯干”未必总是会做具体的事情（比如说我们可以选择性地省略对 render 之外的任何生命周期方法内容的编写），而“灵魂”却总是充实的（render 函数却坚决不能省略）；倘若“躯干”做了点什么，往往都会直接或间接地影响到“灵魂”（因为即便是 render 之外的生命周期逻辑，也大部分是在为 render 层面的效果服务）；“躯干”和“灵魂”一起，共同构成了 React 组件完整而不可分割的“生命时间轴”。</p> <h3 id="拆解-react-生命周期-从-react-15-说起"><a href="#拆解-react-生命周期-从-react-15-说起" class="header-anchor">#</a> 拆解 React 生命周期：从 React 15 说起</h3> <p>我发现时下许多资料在讲解 React 生命周期时，喜欢直接拿 React 16 开刀。这样做虽然省事儿，却也模糊掉了新老生命周期变化背后的“Why”（关于两者的差异，我们会在“03 课时”中详细讲解）。这里为了把这个“Why”拎出来，我将首先带你认识 React 15 的生命周期流程。</p> <p>在 React 15 中，大家需要关注以下几个生命周期方法：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentWillReceiveProps</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">shouldComponentUpdate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentWillMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentWillUpdate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentDidUpdate</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentDidMount</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token function">componentWillUnmount</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><blockquote><p>如果你接触 React 足够早，或许会记得还有 getDefaultProps 和 getInitState 这两个方法，它们都是 React.createClass() 模式下初始化数据的方法。由于这种写法在 ES6 普及后已经不常见，这里不再详细展开。</p></blockquote> <p>这些生命周期方法是如何彼此串联、相互依存的呢？这里我为你总结了一张大图：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5E/31/Ciqc1F-GZbGAGNcBAAE775qohj8453.png" alt="1.png"></p> <p>接下来，我就围绕这张大图，分阶段讨论组件生命周期的运作规律。在学习的过程中，下面这个 Demo 可以帮助你具体地验证每个阶段的工作流程：</p> <p>import React from &quot;react&quot;; import ReactDOM from &quot;react-dom&quot;; // 定义子组件 class LifeCycle extends React.Component {  constructor(props) {    console.log(&quot;进入constructor&quot;);    super(props);    // state 可以在 constructor 里初始化    this.state = { text: &quot;子组件的文本&quot; };  }  // 初始化渲染时调用  componentWillMount() {    console.log(&quot;componentWillMount方法执行&quot;);  }  // 初始化渲染时调用  componentDidMount() {    console.log(&quot;componentDidMount方法执行&quot;);  }  // 父组件修改组件的props时会调用  componentWillReceiveProps(nextProps) {    console.log(&quot;componentWillReceiveProps方法执行&quot;);  }  // 组件更新时调用  shouldComponentUpdate(nextProps, nextState) {    console.log(&quot;shouldComponentUpdate方法执行&quot;);    return true;  } // 组件更新时调用 componentWillUpdate(nextProps, nextState) { console.log(&quot;componentWillUpdate方法执行&quot;); } // 组件更新后调用 componentDidUpdate(preProps, preState) { console.log(&quot;componentDidUpdate方法执行&quot;); } // 组件卸载时调用 componentWillUnmount() { console.log(&quot;子组件的componentWillUnmount方法执行&quot;); } // 点击按钮，修改子组件文本内容的方法 changeText = () =&gt; { this.setState({ text: &quot;修改后的子组件文本&quot; }); }; render() { console.log(&quot;render方法执行&quot;); return ( </p><div className="container"><button onClick="{this.changeText}" className="changeText"> 修改子组件文本内容 </button> <p className="textContent">{this.state.text}</p> <p className="fatherContent">{this.props.text}</p></div> ); } } // 定义 LifeCycle 组件的父组件 class LifeCycleContainer extends React.Component {<p></p> <div class="language- line-numbers-mode"><pre class="language-text"><code>// state 也可以像这样用属性声明的形式初始化 state = { text: &quot;父组件的文本&quot;, hideChild: false }; // 点击按钮，修改父组件文本的方法 changeText = () =&gt; { this.setState({ text: &quot;修改后的父组件文本&quot; }); }; // 点击按钮，隐藏（卸载）LifeCycle 组件的方法 hideChild = () =&gt; { this.setState({ hideChild: true }); }; render() { return ( &lt;div className=&quot;fatherContainer&quot;&gt; &lt;button onClick={this.changeText} className=&quot;changeText&quot;&gt; 修改父组件文本内容 &lt;/button&gt; &lt;button onClick={this.hideChild} className=&quot;hideChild&quot;&gt; 隐藏子组件 &lt;/button&gt; {this.state.hideChild ? null : &lt;LifeCycle text={this.state.text} /&gt;} &lt;/div&gt; ); } } ReactDOM.render(&lt;LifeCycleContainer /&gt;, document.getElementById(&quot;root&quot;)); 
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>该入口文件对应的 index.html 中预置了 id 为 root 的真实 DOM 节点作为根节点，body 标签内容如下：</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token operator">&lt;</span>body<span class="token operator">&gt;</span>
  <span class="token operator">&lt;</span>div id<span class="token operator">=</span><span class="token string">&quot;root&quot;</span><span class="token operator">&gt;</span><span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>body<span class="token operator">&gt;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>这个 Demo 渲染到浏览器上大概是这样的：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CC/Ciqc1F-FU-yAMLh0AABeqOeqLek815.png" alt="Drawing 1.png"></p> <p>此处由于我们强调的是对生命周期执行规律的验证，所以样式上从简，你也可以根据自己的喜好添加 CSS 相关的内容。</p> <p>接下来我们就结合这个 Demo 和开头的生命周期大图，一起来看看挂载、更新、卸载这 3 个阶段，React 组件都经历了哪些事情。</p> <h4 id="mounting-阶段-组件的初始化渲染-挂载"><a href="#mounting-阶段-组件的初始化渲染-挂载" class="header-anchor">#</a> Mounting 阶段：组件的初始化渲染（挂载）</h4> <p>挂载过程在组件的一生中仅会发生一次，在这个过程中，组件被初始化，然后会被渲染到真实 DOM 里，完成所谓的“首次渲染”。</p> <p>在挂载阶段，一个 React 组件会按照顺序经历如下图所示的生命周期：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5E/32/Ciqc1F-GZ1OAWETTAAA3Am2CwU0383.png" alt="3.png"></p> <p>首先我们来看 constructor 方法，该方法仅仅在挂载的时候被调用一次，我们可以在该方法中对 this.state 进行初始化：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token function">constructor</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;进入constructor&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// state 可以在 constructor 里初始化</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> text<span class="token operator">:</span> <span class="token string">&quot;子组件的文本&quot;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>componentWillMount、componentDidMount 方法同样只会在挂载阶段被调用一次。其中 componentWillMount 会在执行 render 方法前被触发，一些同学习惯在这个方法里做一些初始化的操作，但这些操作往往会伴随一些风险或者说不必要性（这一点大家先建立认知，具体原因将在“03 课时”展开讲解）。</p> <p>接下来 render 方法被触发。注意 render 在执行过程中并不会去操作真实 DOM（也就是说不会渲染），它的职能是<strong>把需要渲染的内容返回出来</strong>。真实 DOM 的渲染工作，在挂载阶段是由 ReactDOM.render 来承接的。</p> <p>componentDidMount 方法在渲染结束后被触发，此时因为真实 DOM 已经挂载到了页面上，我们可以在这个生命周期里执行真实 DOM 相关的操作。此外，类似于异步请求、数据初始化这样的操作也大可以放在这个生命周期来做（侧面印证了 componentWillMount 真的很鸡肋）。</p> <p>这一整个流程对应的其实就是我们 Demo 页面刚刚打开时，组件完成初始化渲染的过程。下图是 Demo 中的 LifeCycle 组件在挂载过程中控制台的输出，你可以用它来验证挂载过程中生命周期顺序的正确性：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/D8/CgqCHl-FU_6AeWUcAAB8X4bjwqE102.png" alt="Drawing 3.png"></p> <h4 id="updating-阶段-组件的更新"><a href="#updating-阶段-组件的更新" class="header-anchor">#</a> Updating 阶段：组件的更新</h4> <p>组件的更新分为两种：一种是由父组件更新触发的更新；另一种是组件自身调用自己的 setState 触发的更新。这两种更新对应的生命周期流程如下图所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5E/3C/CgqCHl-GZf-AUjsLAACmOsiQl3M485.png" alt="2.png"></p> <p><strong>componentWillReceiProps 到底是由什么触发的？</strong></p> <p>从图中你可以明显看出，父组件触发的更新和组件自身的更新相比，多出了这样一个生命周期方法：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token function">componentWillReceiveProps</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>在这个生命周期方法里，nextProps 表示的是接收到新 props 内容，而现有的 props （相对于 nextProps 的“旧 props”）我们可以通过 this.props 拿到，由此便能够感知到 props 的变化。</p> <p>写到这里，就不得不在“变化”这个动作上深挖一下了。我在一些社区文章里，包括一些候选人面试时的回答里，都不约而同地见过/听过这样一种说法：<strong>componentWillReceiveProps 是在组件的 props 内容发生了变化时被触发的。</strong></p> <p><strong>这种说法不够严谨</strong>。远的不说，就拿咱们上文给出的 Demo 开刀，该界面的控制台输出在初始化完成后是这样的：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CC/Ciqc1F-FVA6AYiD4AADSl2lr-_Q663.png" alt="Drawing 5.png"></p> <p>注意，我们代码里面，LifeCycleContainer 这个父组件传递给子组件 LifeCycle 的 props 只有一个 text：</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token operator">&lt;</span><span class="token class-name">LifeCycle</span> text<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>text<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>假如我点击“修改父组件文本内容”这个按钮，父组件的 this.state.text 会发生改变，进而带动子组件的 this.props.text 发生改变。此时一定会触发 componentWillReceiveProps 这个生命周期，这是毋庸置疑的：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CC/Ciqc1F-FVBWAEqTGAAEdsvX2TAM747.png" alt="Drawing 6.png"></p> <p>但如果我现在对父组件的结构进行一个小小的修改，给它一个和子组件完全无关的 state（this.state.ownText），同时相应地给到一个修改这个 state 的方法（this.changeOwnText），并用一个新的 button 按钮来承接这个触发的动作。</p> <p>改变后的 LifeCycleContainer 如下所示：</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token comment">// 定义 LifeCycle 组件的父组件</span>
<span class="token keyword">class</span> <span class="token class-name">LifeCycleContainer</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span>
  <span class="token comment">// state 也可以像这样用属性声明的形式初始化</span>
  state <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">&quot;父组件的文本&quot;</span><span class="token punctuation">,</span>
    <span class="token comment">// 新增的只与父组件有关的 state</span>
    <span class="token literal-property property">ownText</span><span class="token operator">:</span> <span class="token string">&quot;仅仅和父组件有关的文本&quot;</span><span class="token punctuation">,</span>
    <span class="token literal-property property">hideChild</span><span class="token operator">:</span> <span class="token boolean">false</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token function-variable function">changeText</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">text</span><span class="token operator">:</span> <span class="token string">&quot;修改后的父组件文本&quot;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token comment">// 修改 ownText 的方法</span>
  <span class="token function-variable function">changeOwnText</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">ownText</span><span class="token operator">:</span> <span class="token string">&quot;修改后的父组件自有文本&quot;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token function-variable function">hideChild</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
      <span class="token literal-property property">hideChild</span><span class="token operator">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span>
      <span class="token operator">&lt;</span>div className<span class="token operator">=</span><span class="token string">&quot;fatherContainer&quot;</span><span class="token operator">&gt;</span>
        <span class="token punctuation">{</span><span class="token comment">/* 新的button按钮 */</span><span class="token punctuation">}</span>
        <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>changeOwnText<span class="token punctuation">}</span> className<span class="token operator">=</span><span class="token string">&quot;changeText&quot;</span><span class="token operator">&gt;</span>
          修改父组件自有文本内容
        <span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>changeText<span class="token punctuation">}</span> className<span class="token operator">=</span><span class="token string">&quot;changeText&quot;</span><span class="token operator">&gt;</span>
          修改父组件文本内容
        <span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>hideChild<span class="token punctuation">}</span> className<span class="token operator">=</span><span class="token string">&quot;hideChild&quot;</span><span class="token operator">&gt;</span>
          隐藏子组件
        <span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>p<span class="token operator">&gt;</span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>ownText<span class="token punctuation">}</span> <span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">&gt;</span>
        <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>hideChild <span class="token operator">?</span> <span class="token keyword">null</span> <span class="token operator">:</span> <span class="token operator">&lt;</span>LifeCycle text<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>text<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">&gt;</span><span class="token punctuation">}</span>
      <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br></div></div><p>新的界面如下图所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CD/Ciqc1F-FVCGAVX_GAAFADHW8-9A107.png" alt="Drawing 7.png"></p> <p>可以看到，this.state.ownText 这个状态和子组件完全无关。但是当我点击“修改父组件自有文本内容”这个按钮的时候，componentReceiveProps 仍然被触发了，效果如下图所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/D8/CgqCHl-FVCqASZNkAAGmF-R62cg649.png" alt="Drawing 8.png"></p> <p>耳听为虚，眼见为实。面对这样的运行结果，我不由得要带你复习一下 React 官方文档中的这句话：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/E1/Ciqc1F-FaGuADV5vAACZ2YRV6qQ941.png" alt="图片7.png"></p> <p><strong>componentReceiveProps 并不是由 props 的变化触发的，而是由父组件的更新触发的</strong>，这个结论，请你谨记。</p> <p><strong>组件自身 setState 触发的更新</strong></p> <p>this.setState() 调用后导致的更新流程，前面大图中已经有体现，这里我直接沿用上一个 Demo 来做演示。若我们点击上一个 Demo 中的“修改子组件文本内容”这个按钮：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/D8/CgqCHl-FVDWABuVmAADVzZuKCO0699.png" alt="Drawing 9.png"></p> <p>这个动作将会触发子组件 LifeCycle 自身的更新流程，随之被触发的生命周期函数如下图增加的 console 内容所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CD/Ciqc1F-FVDuASw5bAAEhb9melJQ452.png" alt="Drawing 10.png"></p> <p>先来说说 componentWillUpdate 和 componentDidUpdate 这一对好基友。</p> <p>componentWillUpdate 会在 render 前被触发，它和 componentWillMount 类似，允许你在里面做一些不涉及真实 DOM 操作的准备工作；而 componentDidUpdate 则在组件更新完毕后被触发，和 componentDidMount 类似，这个生命周期也经常被用来处理 DOM 操作。此外，我们也常常将 componentDidUpdate 的执行作为子组件更新完毕的标志通知到父组件。</p> <p><strong>render 与性能：初识 shouldComponentUpdate</strong></p> <p>这里需要重点提一下 shouldComponentUpdate 这个生命周期方法，它的调用形式如下所示：</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token function">shouldComponentUpdate</span><span class="token punctuation">(</span>nextProps<span class="token punctuation">,</span> nextState<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>render 方法由于伴随着对虚拟 DOM 的构建和对比，过程可以说相当耗时。而在 React 当中，很多时候我们会不经意间就频繁地调用了 render。为了避免不必要的 render 操作带来的性能开销，React 为我们提供了 shouldComponentUpdate 这个口子。</p> <p>React 组件会根据 shouldComponentUpdate 的返回值，来决定是否执行该方法之后的生命周期，进而决定是否对组件进行<strong>re-render</strong>（重渲染）。shouldComponentUpdate 的默认值为 true，也就是说“无条件 re-render”。在实际的开发中，我们往往通过手动往 shouldComponentUpdate 中填充判定逻辑，或者直接在项目中引入 PureComponent 等最佳实践，来实现“有条件的 re-render”。</p> <p>关于 shouldComponentUpdate 及 PureComponent 对 React 的优化，我们会在后续的性能小节中详细展开。这里你只需要认识到 shouldComponentUpdate 的基本使用及其<strong>与 React 性能之间的关联关系</strong>即可。</p> <h4 id="unmounting-阶段-组件的卸载"><a href="#unmounting-阶段-组件的卸载" class="header-anchor">#</a> Unmounting 阶段：组件的卸载</h4> <p>组件的销毁阶段本身是比较简单的，只涉及一个生命周期，如下图所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/EC/CgqCHl-FaHuAVGc_AABE6JqN9E0073.png" alt="图片6.png"></p> <p>对应上文的 Demo 来看，我们点击“隐藏子组件”后就可以把 LifeCycle 从父组件中移除掉，进而实现卸载的效果。整个过程如下图所示：</p> <p><img src="https://s0.lgstatic.com/i/image/M00/5D/CD/Ciqc1F-FVFeABZvpAAO9lJVFKhs335.png" alt="Drawing 12.png"></p> <p>这个生命周期本身不难理解，我们重点说说怎么触发它。组件销毁的常见原因有以下两个。</p> <ul><li>组件在父组件中被移除了：这种情况相对比较直观，对应的就是我们上图描述的这个过程。</li> <li>组件中设置了 key 属性，父组件在 render 的过程中，发现 key 值和上一次不一致，那么这个组件就会被干掉。</li></ul> <p>在本课时，只要能够理解到 1 就可以了。对于 2 这种情况，你只需要先记住有这样一种现象，这就够了。至于组件里面为什么要设置 key，为什么 key 改变后组件就必须被干掉？要回答这个问题，需要你先理解 React 的“调和过程”，而“调和过程”也会是我们第二模块中重点讲解的一个内容。这里我先把这个知识点点出来，方便你定位我们整个知识体系里的<strong>重难点</strong>。</p> <h3 id="总结"><a href="#总结" class="header-anchor">#</a> 总结</h3> <p>在本课时，我们对 React 设计思想中的“虚拟 DOM”和“组件化”这两个关键概念形成了初步的理解，同时也对 React 15 中的生命周期进行了系统的学习和总结。到这里，你已经了解到了 React 生命周期在很长一段“过去”里的形态。</p> <p>而在 React 16 中，组件的生命周期其实已经发生了一系列的变化。这些变化到底是什么样的，它们背后又蕴含着 React 团队怎样的思量呢？</p> <p>古人说“以史为镜，可以知兴衰”。在下个课时，我们将一起去“照镜子”，对 React 新旧生命周期进行对比，并探求变化的动机。</p></div></div>  <div class="page-edit"><!----> <!----> <div class="last-updated"><span class="prefix">上次更新:</span> <span class="time">2023/06/10, 12:06:41</span></div></div> <div class="page-nav-wapper"><div class="page-nav-centre-wrap"><a href="/pages/88bcac/" class="page-nav-centre page-nav-centre-prev"><div class="tooltip">ant-design Spin组件封装</div></a> <a href="/pages/a18549/" class="page-nav-centre page-nav-centre-next"><div class="tooltip">uniapp物联网无网络智能配对模块</div></a></div> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/pages/88bcac/" class="prev">ant-design Spin组件封装</a></span> <span class="next"><a href="/pages/a18549/">uniapp物联网无网络智能配对模块</a>→
      </span></p></div></div></div> <div class="article-list"><div class="article-title"><a href="/archives/" class="iconfont icon-bi">最近更新</a></div> <div class="article-wrapper"><dl><dd>01</dd> <dt><a href="/pages/e3ef00/"><div>
            接雨水
            <!----></div></a> <span class="date">04-08</span></dt></dl><dl><dd>02</dd> <dt><a href="/pages/a5eeb6/"><div>
            vim日常使用记录
            <!----></div></a> <span class="date">04-08</span></dt></dl><dl><dd>03</dd> <dt><a href="/pages/d46779/"><div>
            有效的字母异位词
            <!----></div></a> <span class="date">04-08</span></dt></dl> <dl><dd></dd> <dt><a href="/archives/" class="more">更多文章&gt;</a></dt></dl></div></div></main></div> <div class="footer"><div class="icons"><a href="mailto:izhaong@outlook.com" title="发邮件" target="_blank" class="iconfont icon-youjian"></a><a href="https://github.com/izhaong" title="GitHub" target="_blank" class="iconfont icon-github"></a><a href="https://music.163.com/#/playlist?id=755597173" title="听音乐" target="_blank" class="iconfont icon-erji"></a></div> 
  Theme by
  <a href="https://github.com/xugaoyi/vuepress-theme-vdoing" target="_blank" title="本站主题">Vdoing</a> 
    | Copyright © 2021-2024
    <span>izhaong | <a href="https://github.com/izhaong" target="_blank">github</a> | <a href="http://beian.miit.gov.cn/" target="_blank">蜀ICP备2021031194号</a></span></div> <div class="buttons"><div title="返回顶部" class="button blur go-to-top iconfont icon-fanhuidingbu" style="display:none;"></div> <div title="去评论" class="button blur go-to-comment iconfont icon-pinglun" style="display:none;"></div> <div title="主题模式" class="button blur theme-mode-but iconfont icon-zhuti"><ul class="select-box" style="display:none;"><li class="iconfont icon-zidong">
          跟随系统
        </li><li class="iconfont icon-rijianmoshi">
          浅色模式
        </li><li class="iconfont icon-yejianmoshi">
          深色模式
        </li><li class="iconfont icon-yuedu">
          阅读模式
        </li></ul></div></div> <div class="body-bg" style="background:url() center center / cover no-repeat;opacity:0.5;"></div> <!----> <!----></div><div class="global-ui"><div></div></div></div>
    <script src="/assets/js/app.6d26e8d4.js" defer></script><script src="/assets/js/2.8273876b.js" defer></script><script src="/assets/js/126.ccdb194e.js" defer></script>
  </body>
</html>
